#include <algorithm>
#include <arpa/inet.h>
#include <atomic>
#include <cerrno>
#include <chrono>
#include <iostream>
#include <memory>
#include <mutex>
#include <netinet/in.h>
#include <stdexcept>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <thread>
#include <unistd.h>
#include <vector>

class UdpServer {
public:
	explicit UdpServer(int port = 0) : port_(port) {
		server_fd_ = socket(AF_INET, SOCK_DGRAM, 0);
		if (server_fd_ == -1) {
			throw std::runtime_error("socket() failed: " + std::string(strerror(errno)));
		}

		sockaddr_in addr{};
		addr.sin_family      = AF_INET;
		addr.sin_addr.s_addr = INADDR_ANY;
		addr.sin_port        = htons(port);

		if (bind(server_fd_, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
			close(server_fd_);
			throw std::runtime_error("bind() failed: " + std::string(strerror(errno)));
		}

		// 获取实际分配的端口（当传入0时）
		if (port == 0) {
			socklen_t len = sizeof(addr);
			if (getsockname(server_fd_, (struct sockaddr *) &addr, &len) == -1) {
				close(server_fd_);
				throw std::runtime_error("getsockname() failed: " + std::string(strerror(errno)));
			}
			port_ = ntohs(addr.sin_port);
		}
	}

	~UdpServer() {
		if (server_fd_ != -1) {
			close(server_fd_);
		}
	}

	int getPort() const { return port_; }
	int getSocket() const { return server_fd_; }

private:
	int server_fd_ = -1;
	int port_;
};

class ServiceManager {
public:
	ServiceManager() : epoll_fd_(epoll_create1(0)) {
		if (epoll_fd_ == -1) {
			throw std::runtime_error("epoll_create1() failed: " + std::string(strerror(errno)));
		}
	}

	~ServiceManager() {
		if (epoll_fd_ != -1) {
			close(epoll_fd_);
		}
	}

	int createService() {
		std::lock_guard<std::mutex> lock(mutex_);

		try {
			auto server = std::make_shared<UdpServer>();
			int port    = server->getPort();

			// 配置epoll事件
			struct epoll_event ev;
			ev.events  = EPOLLIN | EPOLLET; // 边缘触发模式
			ev.data.fd = server->getSocket();

			if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, server->getSocket(), &ev) == -1) {
				throw std::runtime_error("epoll_ctl() ADD failed: " + std::string(strerror(errno)));
			}

			servers_.emplace_back(server);
			return port;
		} catch (...) {
			// 异常时清理已创建的资源
			for (auto &srv: servers_) {
				if (srv->getPort() == 0) {
					destroyService(srv->getPort());
				}
			}
			throw;
		}
	}

	void destroyService(int port) {
		std::lock_guard<std::mutex> lock(mutex_);
		auto it = std::find_if(servers_.begin(), servers_.end(), [port](const std::shared_ptr<UdpServer> &srv) { return srv->getPort() == port; });
		if (it != servers_.end()) {
			int fd = (*it)->getSocket();

			// 从epoll移除
			if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, nullptr) == -1 && errno != ENOENT) {
				std::cerr << "epoll_ctl() DEL failed: " << strerror(errno) << std::endl;
			}

			servers_.erase(it);
		}
	}

	void run() {
		constexpr int MAX_EVENTS = 10;
		struct epoll_event events[MAX_EVENTS];

		while (running_.load(std::memory_order_relaxed)) {
			int n = epoll_wait(epoll_fd_, events, MAX_EVENTS, 100);
			if (n == -1) {
				if (errno == EINTR) continue;
				std::cerr << "epoll_wait() error: " << strerror(errno) << std::endl;
				break;
			}

			for (int i = 0; i < n; ++i) {
				auto it = std::find_if(servers_.begin(), servers_.end(), [fd = events[i].data.fd](const auto &srv) { return srv->getSocket() == fd; });
				if (it != servers_.end()) {
					handleData(*it);
				}
			}
		}
	}

	void start() {
		running_.store(true, std::memory_order_relaxed);
		worker_ = std::thread(&ServiceManager::run, this);
	}

	void stop() {
		running_.store(false, std::memory_order_relaxed);
		if (worker_.joinable()) {
			worker_.join();
		}
	}

private:
	void handleData(const std::shared_ptr<UdpServer> &server) {
		constexpr int BUFFER_SIZE = 1024;
		char buffer[BUFFER_SIZE];
		sockaddr_in client_addr{};
		socklen_t len = sizeof(client_addr);

		ssize_t n = recvfrom(server->getSocket(), buffer, BUFFER_SIZE, 0, (struct sockaddr *) &client_addr, &len);

		if (n > 0) {
			std::cout << "Received " << n << " bytes on port " << server->getPort() << std::endl;
		} else if (n == -1) {
			std::cerr << "recvfrom() error: " << strerror(errno) << std::endl;
		}
	}

	std::vector<std::shared_ptr<UdpServer>> servers_;
	std::mutex mutex_;
	int epoll_fd_;
	std::thread worker_;
	std::atomic<bool> running_{false};
};

int main() {
	try {
		ServiceManager manager;
		manager.start();

		// 创建多个服务
		std::vector<int> ports;
		for (int i = 0; i < 10; ++i) {
			ports.push_back(manager.createService());
		}

		std::cout << "Created services on ports: ";
		for (int port: ports) {
			std::cout << port << " ";
		}
		std::cout << std::endl;

		std::this_thread::sleep_for(std::chrono::seconds(5));

		// 清理服务
		for (int port: ports) {
			manager.destroyService(port);
		}

		manager.stop();
	} catch (const std::exception &e) {
		std::cerr << "Exception: " << e.what() << std::endl;
		return 1;
	}
	return 0;
}
